package com.junxonline.plat.config;

import com.junxonline.plat.shiro.realm.CommonRealm;
import com.junxonline.plat.shiro.filter.LoginFilter;
import com.junxonline.plat.shiro.filter.PermissionFilter;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;

import org.apache.shiro.mgt.SecurityManager;

import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author JunX
 * @ClassName: ShiroConfig
 * @Description: Shiro配置类
 */
@Configuration
public class ShiroConfig {

    private Logger logger = LogManager.getLogger();

    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    public PermissionFilter permissionFilter() {
        return new PermissionFilter();
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactory(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(securityManager);

        // 添加自定义过滤器
        Map<String, Filter> filters = new HashMap<String, Filter>();
        filters.put("login", new LoginFilter());
        filters.put("permission", permissionFilter());

        shiroFilter.setFilters(filters);

        shiroFilter.setUnauthorizedUrl("/403");

        // 配置过滤器链
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();

        // 配置注销过滤器
        filterChainDefinitionMap.put("/admin/logout", "logout");

        // 过滤链定义，从上向下顺序执行，一般将/**放在最为下边

        // 配置不会被拦截的链接 顺序判断
        filterChainDefinitionMap.put("/401", "anon");
        filterChainDefinitionMap.put("/403", "anon");
        filterChainDefinitionMap.put("/", "anon");

        // 需要拦截的URL
        filterChainDefinitionMap.put("/admin/server/**", "login");
        filterChainDefinitionMap.put("/admin/menu/getNavMenu", "login");
        filterChainDefinitionMap.put("/admin/menu/getButton", "login");
        filterChainDefinitionMap.put("/admin/**", "login, permission");

        shiroFilter.setFilterChainDefinitionMap(filterChainDefinitionMap);

        logger.info("shiroFilter创建成功");

        return shiroFilter;

    }

    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(commonRealm());

        /*
         * 关闭shiro自带的session，详情见文档
         * http://shiro.apache.org/session-management.html#SessionManagement-StatelessApplications%28Sessionless%29
         */
        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
        DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
        subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
        securityManager.setSubjectDAO(subjectDAO);

        return securityManager;
    }

    @Bean
    public CommonRealm commonRealm() {
        CommonRealm commonRealm = new CommonRealm();
        return commonRealm;
    }

    /**
     * 添加Shiro注解支持
     */
    @Bean
    @DependsOn("lifecycleBeanPostProcessor")
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        // 强制cglib代理
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    /**
     * 注册自定义Filter 同时设为Enable
     * 即可享受Spring的自动注入 又不会影响到Shiro的过滤链失效
     * @param filter
     * @return
     */
    @Bean
    public FilterRegistrationBean registration(PermissionFilter filter) {
        FilterRegistrationBean registration = new FilterRegistrationBean(filter);
        registration.setEnabled(false);
        return registration;
    }

}
